#include "YGPlatform.h"

#if (YG_OS_TYPE == YG_OS_TYPE_WINDOWSMOBILE)

#include "YGRenderMethodManagerWM6.h"
#include "YGWindowWM6.h"

#include "YGFileManager.h"

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

namespace YoghurtGum
{

	typedef RenderMethod* (*DLL_START_PLUGIN)(Device*);

	RenderMethodManagerWM6::RenderMethodManagerWM6()
	{
		m_RendererTotal = 0;
	}

	RenderMethodManagerWM6::~RenderMethodManagerWM6()
	{

	}

	bool RenderMethodManagerWM6::Destroy()
	{
		return true;
	}

	void RenderMethodManagerWM6::InstallRenderer(const char* a_PluginName)
	{
		// Dear Ogre: I love you I love you I love you
		// I am totally stealing this

		Log::GetSingleton() << "Installing renderer '" << a_PluginName << "'" << ENDL;

		wchar_t plugin[YG_MAX_PATH] = { 0 };
		char dir[256];
		strcpy(dir, FileManager::Get().AddWorkingDirectory((char*)a_PluginName));
		mbstowcs(plugin, dir, strlen(dir));

#if (YG_RUN == YG_RUN_DEBUG)

		wcscat(plugin, TEXT("_d.dll"));

#elif (YG_RUN == YG_RUN_RELEASE)

		wcscat(plugin, TEXT(".dll"));

#endif

		Log::GetSingleton() << "Final path '" << plugin << "'" << ENDL;

		HINSTANCE lib = (HINSTANCE)LoadLibrary(plugin);

		if (!lib)
		{
			Error::LastError();
			ERROR_EXPLAIN("Something went wrong loading '%s' (%s).", a_PluginName, plugin);
			return;
		}

		DLL_START_PLUGIN func_start = (DLL_START_PLUGIN)GetProcAddressA(lib, "Install");
		if (!func_start)
		{
			Error::LastError();
			ERROR_EXPLAIN("Something went wrong while getting a handle to the plugin's Install function.");
			return;
		}

		//RenderMethod* loaded = func_start(&Log::GetSingleton());
		RenderMethod* loaded = func_start(&Device::Get());
		this->AddRenderer(loaded, loaded->GetName());	
	}

	void RenderMethodManagerWM6::AddRenderer(RenderMethod* a_RenderMethod, const char* a_Name)
	{
		Log::GetSingleton() << "Adding renderer '" << a_Name << "'" << ENDL;

		m_RendererOptions[m_RendererTotal] = a_RenderMethod;
		strcpy(m_RendererNames[m_RendererTotal], a_Name);
		m_RendererTotal++;
	}

	RenderMethod* RenderMethodManagerWM6::GetCurrent()
	{
		return m_RendererOptions[0];	
	}

	RenderMethod* RenderMethodManagerWM6::GetRenderMethod(const char* a_Name)
	{
		for (int i = 0; i < m_RendererTotal; i++)
		{
			if (!strcmp(a_Name, m_RendererNames[i]))
			{
				return m_RendererOptions[i];
			}
		}

		Log::GetSingleton() << "ERROR! Could not find a render method called '" << a_Name << "'." << ENDL;

		return NULL;
	}

	bool RenderMethodManagerWM6::SetProperty(const char* a_Name, void* a_Data)
	{
		if (!strcmp(a_Name, "WindowHandle"))
		{
			m_WindowHandle = *(HWND*)a_Data;
			return true;
		}

		return false;
	}

	RenderMethod* RenderMethodManagerWM6::ChooseRenderMethod(Window* a_Window)
	{
		WindowWM6* win = (WindowWM6*)a_Window;

		RenderMethod* rm = NULL;
		for (int i = 0; i < m_RendererTotal; i++)
		{
			Log::GetSingleton() << "Testing: " << m_RendererOptions[i]->GetName() << ENDL;

			m_RendererOptions[i]->SetProperty("WindowHandle", win->GetProperty("WindowHandle"));
			bool init = m_RendererOptions[i]->Init();
			m_RendererOptions[i]->SetClearColor(Color(0.f, 0.f, 0.f));
			if (!init || !m_RendererOptions[i]->Clear() || !m_RendererOptions[i]->PreRender() || !m_RendererOptions[i]->PostRender())
			{
				Log::GetSingleton() << "Selected render method does not work on this device." << ENDL;
			}
			else
			{
				rm = m_RendererOptions[i];
				break;
			}
		}
		
		return rm;
	}

}

#endif
